package com.ziq.zcamp.post

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.EditText
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.core.view.isVisible
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.amap.api.services.core.PoiItem
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.listener.OnResultCallbackListener
import com.ziq.base.base.BaseActivity
import com.ziq.base.extension.binding
import com.ziq.base.extension.click
import com.ziq.base.utils.LogUtil
import com.ziq.base.utils.SystemBarUtil
import com.ziq.base.utils.permission.PermissionUtil
import com.ziq.zcamp.R
import com.ziq.zcamp.api.service.ServiceModule.Companion.onApiFail
import com.ziq.zcamp.bean.place.CampListItem
import com.ziq.zcamp.bean.place.LocationInfo
import com.ziq.zcamp.bean.post.CampInfo
import com.ziq.zcamp.bean.post.ImageInfo
import com.ziq.zcamp.bean.post.PostMedia
import com.ziq.zcamp.databinding.ActivityPublichsDynamicBinding
import com.ziq.zcamp.main.MainActivityViewModel
import com.ziq.zcamp.manager.DataManager
import com.ziq.zcamp.manager.GlobalContextManager
import com.ziq.zcamp.manager.PostManager
import com.ziq.zcamp.util.KeyboardHelper
import com.ziq.zcamp.util.PictureUtil
import com.ziq.zcamp.util.PictureUtil.Companion.getPath
import com.ziq.zcamp.util.TimeUtil
import com.ziq.zcamp.util.ToastUtil
import com.ziq.zcamp.util.list.ObservableListUtil
import com.ziq.zcamp.view.edit.SupportTopicsEditText
import com.ziq.zcamp.view.edit.SymbolTriggerCallback
import dagger.hilt.android.AndroidEntryPoint
import java.util.*
import kotlin.math.max


@AndroidEntryPoint
class PublishDynamicActivity : BaseActivity() {

    companion object {
        private const val PICTURE_LIST = "picture_list"
        private const val CAMP_INFO = "camp_info"
        fun startActivity(context: Context, list: ArrayList<PostMedia>, campInfo: CampInfo? = null){
            val intent = Intent(context, PublishDynamicActivity::class.java)
            intent.putParcelableArrayListExtra(PICTURE_LIST, list)
            if(campInfo != null){
                intent.putExtra(CAMP_INFO, campInfo)
            }
            GlobalContextManager.startActivity(context, intent)
        }
    }

    private val binding: ActivityPublichsDynamicBinding by binding()

    val mViewModel: PublishDynamicViewModel by viewModels()
    val mTopicsViewModel: TopicsViewModel by viewModels()

    private var campInfo: CampListItem? = null
    private val pictureList = mutableListOf<PostMedia>()
    private var adapter: PublishPictureAdapter? = null
    private var locationInfo: LocationInfo? = null
    private var lastStartDate: Date? = null
    private var lastEndDate: Date? = null


    private var editContentHasFocus = false
    private var keyboardIsOpen = false
    private var currentSearchTopicsOfIndex = -1
    private var currentSearchTopics :String ?= null

    var poiItem : PoiItem? = null

    private var isCampDayFirstTime = true

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        try {
            if(intent.hasExtra(PICTURE_LIST)){
                val pictureArray  = intent.getParcelableArrayListExtra<PostMedia>(PICTURE_LIST)
                updateDataList(pictureArray)
            }

            if(intent.hasExtra(CAMP_INFO)){
                campInfo  = intent.getSerializableExtra(CAMP_INFO) as CampListItem?
            }
        }catch (e:Exception){
            println("$e")
        }
        binding.root

        binding.back.click {
            hideKeyboard()
            onBackPressedDispatcher.onBackPressed()
        }
        //输入框、话题
        initTopicsUI()
        //图片选择、拖拽
        initPictureListLayout()

        binding.ivLocationClear.click {
            campInfo = null
            poiItem = null
            locationInfo = null
            updateForLocationSelected()
        }

        binding.llLocationInfo.click {
            hideKeyboard()
            PermissionUtil.requestLocationPermission(this, onGrant = {
                val intent = Intent(this, SelectLocationTabActivity::class.java)
                intent.putExtra(SelectLocationTabActivity.SELECTED_POI, poiItem)
                intent.putExtra(SelectLocationTabActivity.SELECTED_CAMP, campInfo)
                selectLocationLauncher.launch(intent)
            })
        }

        binding.llCampDay.click {
            CampDaySelectorDialog(this, isCampDayFirstTime, lastStartDate, lastEndDate).setOnNextListener(
                callback = fun(start: Date?, end: Date?){
                    lastStartDate = start
                    lastEndDate = end
                    updateCampDayUI()
                }
            ).show()
            isCampDayFirstTime = false
        }

        binding.send.click {
            hideKeyboard()
            val title = binding.editTitle.text.toString().trim()
            val content = binding.editContent.textContent
            val filePaths = mutableListOf<String>()
            val tempDataList = mutableListOf<PostMedia>()
            val resultPaths = mutableListOf<ImageInfo>()
            for (item in pictureList){
                val imageInfo = ImageInfo().apply {
                    url = ""
                    width = item.getWidth()
                    height = item.getHeight()
                }
                if(item.localMedia != null){
                    filePaths.add(getPath(item.localMedia!!))
                    tempDataList.add(item)
                } else if(item.networkInfo != null){
                    imageInfo.url = item.getUrl()
                }
                resultPaths.add(imageInfo)
            }

            val topicsList =  binding.editContent.topicList
            showLoading()
            mViewModel.uploadMultiImage(filePaths,
                 onFinished = {
                    var hasUploadFail = false
                    for (item in it){
                        if(!(item.isSuccess && item.data?.url != null && item.data?.url!!.isNotEmpty())){
                            hasUploadFail = true
                        }
                    }
                    if(!hasUploadFail){
                        for (item in it){
                            val dataIndex = pictureList.indexOf(tempDataList[item.index!!])
                            if(dataIndex >= 0 && dataIndex < resultPaths.size){
                                resultPaths[dataIndex].url = item.data?.url
                            }
                        }
                        mViewModel.sendPosting(title, content, resultPaths.toList(), locationInfo, campInfo, lastStartDate, lastEndDate,
                            topicsList,
                            onSuccess = {
                                hideLoading()
                                DataManager.increasePostingListVersion()
                                DataManager.increasePostingPublishVersion()
                                Toast.makeText(this, "发帖成功", Toast.LENGTH_SHORT).show()
                                finish()
                            }, onFail = {
                                onApiFail(it)
                                hideLoading()
                            }
                        )
                    } else {
                        val errMsg = GlobalContextManager.getString(R.string.publish_photo_upload_fail)
                        Toast.makeText(this, errMsg, Toast.LENGTH_SHORT).show()
                        hideLoading()
                    }
                }
            )
        }



        updateForLocationSelected()
        updateCampDayUI()
    }

    fun initPictureListLayout(){
        binding.flowLayout.setVerticalSpacing(GlobalContextManager.getResources().getDimensionPixelSize(R.dimen.dimens_dip_4))

        binding.recyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)
        adapter = PublishPictureAdapter(pictureList)
        binding.recyclerView.adapter = adapter
        val itemTouchHelper = ItemTouchHelper(
            RecyclerViewDragDeleteHelper(adapter!!, binding.delArea,
                object : RecyclerViewDragDeleteHelper.DragStateCallback {

                    override fun isInside(
                        itemX: Int,
                        itemY: Int,
                        itemWidth: Int,
                        itemHeight: Int,
                        delAreaX: Int,
                        delAreaY: Int,
                        delAreaWidth: Int,
                        delAreaHeight: Int
                    ): Boolean? {
                        return (itemY + itemHeight + delAreaHeight) >= delAreaY
                    }

                    override fun onDraw(viewHolder: RecyclerView.ViewHolder, isInside: Boolean) {
                        if(isInside){
                            binding.delArea.alpha = 0.5f
                        } else {
                            binding.delArea.alpha = 1f
                        }

                    }

                    override fun isRemovable(position: Int, isInside: Boolean): Boolean {
                        if(pictureList.size <= 1 && isInside){
                            ToastUtil.showToast(this@PublishDynamicActivity, R.string.publish_images_limit)
                            return false
                        }
                        return super.isRemovable(position, isInside)
                    }

                    override fun onDrag(viewHolder: RecyclerView.ViewHolder?, isDragging: Boolean, isDelete: Boolean) {
                        if (isDragging){
                            binding.delArea.visibility = View.VISIBLE
                            //如果需要执行放大动画
                            if(viewHolder != null){
                                viewHolder.itemView.animate().scaleXBy(0.1f).scaleYBy(0.1f).duration = 100
                            }
                        } else {
                            binding.delArea.visibility = View.INVISIBLE
                            //需要松手后才能执行
                            if(viewHolder != null){
                                if(isDelete){
                                    viewHolder.itemView.scaleX = 1f
                                    viewHolder.itemView.scaleY = 1f
                                    viewHolder.itemView.visibility = View.INVISIBLE
                                }else {
                                    viewHolder.itemView.animate().scaleX(1f).scaleY(1f).duration = 100
                                }
                            }
                        }
                    }

                    override fun afterRemove() {
                        super.afterRemove()
                        updateAddIcon()
                    }
                })
        )
        itemTouchHelper.attachToRecyclerView(binding.recyclerView)

        binding.addPic.click {
            hideKeyboard()
            val selectMedia = mutableListOf<LocalMedia>()
            var maxCount = 18
            if(pictureList.isNotEmpty()){
                for (item in pictureList){
                    if(item.localMedia != null){
                        selectMedia.add(item.localMedia!!)
                    }
                }
            }
            PictureUtil.selectPicture(this, selectMedia, object :
                OnResultCallbackListener<LocalMedia> {
                override fun onResult(result: MutableList<LocalMedia>?) {
                    val temp = mutableListOf<PostMedia>()
                    if(result != null){
                        for (item in result){
                            temp.add(PostMedia().apply {
                                localMedia = item
                            })
                        }
                    }
                    updateDataList(temp)
                }

                override fun onCancel() {
                }

            }, maxSelectNum = maxCount)
        }
    }

    fun initTopicsUI(){

        binding.editContent.setOnFocusChangeListener { _, hasFocus ->
            editContentHasFocus = hasFocus
            if (hasFocus && keyboardIsOpen){
                showTopicsInfo()
            }else if (!hasFocus && keyboardIsOpen){
                dismissTopicsInfo()
            }else{
                dismissTopicsInfo()
            }
        }

        binding.tvTopicsInfo.click {
            binding.editContent.text?.insert(binding.editContent.selectionStart,
                SupportTopicsEditText.SYMBOL)
        }

        binding.tvTopicsInfoPopup.click {
            binding.editContent.text?.insert(binding.editContent.selectionStart,
                SupportTopicsEditText.SYMBOL)
        }

        binding.tvTopicsComplete.click {
            KeyboardHelper.hideSoftInputForce(this@PublishDynamicActivity, binding.root.windowToken)
        }

        binding.rvTopicsList.layoutManager = LinearLayoutManager(this)
        val adapter = TopicsAdapter(dataList = mTopicsViewModel.mTopicsList, apply = {
            if (currentSearchTopicsOfIndex!=-1){
                val topics = "#$it "
                binding.editContent.editableText.replace(currentSearchTopicsOfIndex,
                    (currentSearchTopicsOfIndex + 1 + (currentSearchTopics?.length ?: 0)).coerceAtMost(
                        binding.editContent.editableText.length
                    ),topics)
            }
        }, createTopics = {
            if (currentSearchTopicsOfIndex!=-1){
                val topics = "#$it "
                binding.editContent.editableText.replace(currentSearchTopicsOfIndex,
                    (currentSearchTopicsOfIndex + 1 + (currentSearchTopics?.length ?: 0)).coerceAtMost(
                        binding.editContent.editableText.length
                    ),topics)
            }
        })
        binding.rvTopicsList.adapter = adapter
        ObservableListUtil.observableListBind(adapter.dataList, adapter)

        binding.editContent.setSymbolTriggerCallback(object : SymbolTriggerCallback {

            override fun apply(editText: EditText?) {
                KeyboardHelper.showSoftInput(this@PublishDynamicActivity, editText)
            }

            override fun search(startOfSymbol: Int, s: String?) {
                if (startOfSymbol == SupportTopicsEditText.NOT_SEARCH){
                    dismissTopicsList()
                    return
                }
                showTopicsList()
                currentSearchTopicsOfIndex = if (startOfSymbol == SupportTopicsEditText.DEFAULT_SEARCH){
                    max(binding.editContent.selectionStart-1,0)
                }else{
                    startOfSymbol
                }
                currentSearchTopics = s
                mTopicsViewModel.searchTopics(s)
            }

            override fun overflowTopics(showMore: Boolean) {
                binding.vTopicsMore.isVisible = showMore
            }
        })

        window.decorView.let {
            SystemBarUtil.addSystemBarHeightChangeCallBack(it) { statusBarHeight: Int, navigationBarHeight: Int, keyboardHeight: Int ->
                val isPopup = keyboardHeight > 0
                keyboardIsOpen = isPopup
                if (isPopup && editContentHasFocus){
                    showTopicsInfo()
                }else if (isPopup && !editContentHasFocus){
                    dismissTopicsInfo()
                } else{
                    dismissTopicsInfo()
                }
            }
        }

    }

    private fun showTopicsInfo(){
        binding.clTopicsComplete.visibility = View.VISIBLE
        if (binding.llTopicsPopup.visibility == View.VISIBLE){
            binding.tvTopicsInfo.visibility = View.INVISIBLE
        }else{
            binding.tvTopicsInfo.visibility = View.VISIBLE
        }
    }

    private fun dismissTopicsInfo(){
        binding.clTopicsComplete.visibility = View.GONE
        binding.tvTopicsInfo.visibility = View.VISIBLE
    }

    private fun showTopicsList(){
        binding.llTopicsPopup.visibility = View.VISIBLE
        binding.rvTopicsList.visibility = View.VISIBLE
        binding.tvTopicsInfo.visibility = View.INVISIBLE
    }

    private fun dismissTopicsList(){
        binding.llTopicsPopup.visibility = View.GONE
        binding.rvTopicsList.visibility = View.GONE
        binding.tvTopicsInfo.visibility = View.VISIBLE
    }

    fun hideKeyboard(){
        KeyboardHelper.hideSoftInputForce(this, binding.root.windowToken)
    }

    fun updateDataList(result: List<PostMedia>?){
        if(result != null){
            pictureList.clear()
            pictureList.addAll(result)
            adapter?.notifyDataSetChanged()
            updateAddIcon()
        }
    }

    fun updateAddIcon(){
        if(pictureList.size == 18){
            binding.addPic.visibility = View.GONE
        } else {
            binding.addPic.visibility = View.VISIBLE
        }
    }

    fun showLoading(){
        binding.flProgress.visibility = View.VISIBLE
        binding.loadingView.startAnim()
    }

    fun hideLoading(){
        binding.flProgress.visibility = View.GONE
        binding.loadingView.stopAnim()
    }

    private val selectLocationLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ activityResult ->
        if(activityResult.resultCode == Activity.RESULT_OK){
            if(activityResult.data?.hasExtra(SelectLocationTabActivity.SELECTED_POI)!!){
                poiItem = activityResult.data?.getParcelableExtra<PoiItem>(SelectLocationTabActivity.SELECTED_POI)
            }
            if(activityResult.data?.hasExtra(SelectLocationTabActivity.SELECTED_CAMP)!!){
                campInfo = activityResult.data?.getSerializableExtra(SelectLocationTabActivity.SELECTED_CAMP) as CampListItem?
            }
        }
        updateForLocationSelected()
    }
    fun updateForLocationSelected(){
        if(campInfo != null){
            locationInfo = null
            poiItem = null
            binding.llLocationInfo.isSelected = true
            binding.tvLocation.text = "${campInfo?.campName}"
            binding.tvLocation.requestLayout()
            binding.ivLocationArrow.visibility = View.GONE
            binding.ivLocationClear.visibility = View.VISIBLE
        } else if(poiItem != null){
            campInfo = null
            locationInfo = LocationInfo()
            locationInfo?.site = poiItem!!.title
            locationInfo?.longitude = "${poiItem!!.latLonPoint.longitude}"
            locationInfo?.latitude = "${poiItem!!.latLonPoint.latitude}"
            locationInfo?.adcode = poiItem!!.adCode
            locationInfo?.citycode = poiItem!!.cityCode

            binding.llLocationInfo.isSelected = true
            binding.tvLocation.text = "${locationInfo?.site}"
            binding.tvLocation.requestLayout()
            binding.ivLocationArrow.visibility = View.GONE
            binding.ivLocationClear.visibility = View.VISIBLE
        } else if (locationInfo != null) {
            binding.llLocationInfo.isSelected = true
            binding.tvLocation.text = "${locationInfo?.site}"
            binding.tvLocation.requestLayout()
            binding.ivLocationArrow.visibility = View.GONE
            binding.ivLocationClear.visibility = View.VISIBLE
        } else {
            binding.llLocationInfo.isSelected = false
            binding.tvLocation.text = GlobalContextManager.getString(R.string.add_location)
            binding.tvLocation.requestLayout()
            binding.ivLocationArrow.visibility = View.VISIBLE
            binding.ivLocationClear.visibility = View.GONE
        }
    }

    @SuppressLint("SetTextI18n")
    fun updateCampDayUI(){
        if(lastStartDate != null){
            binding.llCampDay.isSelected = true
            binding.tvCampDay.text = "露营日：${TimeUtil.getCampDayTime(lastStartDate?.time, lastEndDate?.time)}"
            binding.ivCampDayNew.visibility = View.GONE
        } else {
            binding.llCampDay.isSelected = false
            binding.ivCampDayNew.visibility = View.VISIBLE
            binding.tvCampDay.text = GlobalContextManager.getString(R.string.select_camp_day)
        }
    }

}